// 文件路径: dbms/Launcher.java
package com.dbms;

import com.dbms.cluster.ClusterManager;
import com.dbms.cluster.NodeInfo;
import com.dbms.service.IDbmsService;
import com.dbms.service.LocalDbmsService;
import com.dbms.service.RemoteDbmsService;
import com.dbms.ui.GuiApplication;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextInputDialog;
import javafx.stage.Stage;

import java.io.IOException;
import java.util.Optional;

/**
 * DBMS应用启动器（JavaFX GUI）
 * 功能：提供可视化模式选择界面，支持四种启动模式，简化用户操作
 * 1. 本地模式（GUI）：单机GUI客户端，直接连接本地数据库文件
 * 2. 客户端模式（GUI）：远程GUI客户端，连接指定服务器
 * 3. 服务器模式（后台）：无界面后台服务器，等待客户端连接
 * 4. 集群节点模式（后台）：作为集群节点启动，支持主从/分片模式
 *
 * 【已增强】
 * - 集群节点模式启动时，自动识别节点角色（主/从）并向用户展示，提升集群部署透明度
 * - 增加输入校验（如IP端口格式、节点ID合法性），优化错误提示
 */
public class Launcher extends Application {

    /**
     * JavaFX应用入口方法：初始化启动模式选择弹窗，处理用户选择
     * @param primaryStage 主舞台（未直接使用，主要用于弹窗载体）
     */
    @Override
    public void start(Stage primaryStage) {
        // 1. 创建启动模式选择弹窗（确认对话框）
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("DBMS 启动模式选择");
        alert.setHeaderText("请选择要启动的模式");
        alert.setContentText("选择一种模式来启动应用程序。");

        // 2. 定义四种启动模式的按钮
        ButtonType buttonTypeLocal = new ButtonType("本地模式 (GUI)");       // 本地GUI
        ButtonType buttonTypeClient = new ButtonType("客户端模式 (GUI)");    // 远程GUI客户端
        ButtonType buttonTypeServer = new ButtonType("服务器模式 (后台)");    // 后台服务器
        ButtonType buttonTypeCluster = new ButtonType("集群节点模式 (后台)"); // 集群节点
        ButtonType buttonTypeCancel = new ButtonType("取消");                // 取消启动

        // 设置弹窗按钮组
        alert.getButtonTypes().setAll(buttonTypeLocal, buttonTypeClient, buttonTypeServer, buttonTypeCluster, buttonTypeCancel);

        // 3. 处理用户选择结果
        Optional<ButtonType> result = alert.showAndWait();
        if (result.isPresent()) {
            // -------------------------- 分支1：本地模式（GUI）--------------------------
            if (result.get() == buttonTypeLocal) {
                System.out.println("Starting in Local GUI Mode...");
                // 创建本地数据库服务实例（直接操作本地文件）
                IDbmsService localService = new LocalDbmsService();
                // 设置GUI应用的数据库服务
                GuiApplication.setDbmsService(localService);
                // 启动GUI应用（新舞台）
                new GuiApplication().start(new Stage());

                // -------------------------- 分支2：客户端模式（GUI）--------------------------
            } else if (result.get() == buttonTypeClient) {
                System.out.println("Starting in Client GUI Mode...");
                // 创建IP端口输入弹窗（默认值为本地测试地址）
                TextInputDialog dialog = new TextInputDialog("127.0.0.1:9991");
                dialog.setTitle("连接到服务器");
                dialog.setHeaderText("请输入服务器的 IP地址:端口号");
                dialog.setContentText("地址:");

                // 处理IP端口输入结果
                Optional<String> ipResult = dialog.showAndWait();
                ipResult.ifPresent(address -> {
                    try {
                        // 解析IP和端口（格式：IP:端口）
                        String[] parts = address.split(":");
                        if (parts.length != 2) {
                            showError("格式错误", "请输入有效的 IP地址:端口号 格式。");
                            return;
                        }
                        String host = parts[0]; // 服务器IP
                        int port = Integer.parseInt(parts[1]); // 服务器端口

                        // 创建远程数据库服务实例（连接指定服务器）
                        IDbmsService remoteService = new RemoteDbmsService(host, port);
                        GuiApplication.setDbmsService(remoteService);
                        // 启动GUI应用
                        new GuiApplication().start(new Stage());

                    } catch (NumberFormatException e) {
                        // 端口号非数字时的错误提示
                        showError("端口无效", "端口号必须是一个有效的数字。");
                    } catch (IOException e) {
                        // 连接失败时的错误提示（如服务器未启动、网络问题）
                        showError("连接失败", "无法连接到服务器: " + e.getMessage());
                    }
                });

                // -------------------------- 分支3：服务器模式（后台）--------------------------
            } else if (result.get() == buttonTypeServer) {
                System.out.println("Starting in Server Mode...");
                // 显示启动提示（后台启动，用户需查看控制台）
                showInfo("服务器启动", "服务器正在后台启动，请查看控制台输出。");
                // 开启新线程启动服务器（避免阻塞GUI线程）
                new Thread(() -> DbmsServer.main(new String[]{})).start();

                // -------------------------- 分支4：集群节点模式（后台）【增强版】--------------------------
            } else if (result.get() == buttonTypeCluster) {
                System.out.println("Starting in Cluster Node Mode...");
                // 创建节点ID输入弹窗（默认值为"node1"）
                TextInputDialog dialog = new TextInputDialog("node1");
                dialog.setTitle("启动集群节点");
                dialog.setHeaderText("请输入要启动的节点ID (例如: node1, node2)");
                dialog.setContentText("节点ID:");

                // 处理节点ID输入结果
                Optional<String> nodeIdResult = dialog.showAndWait();
                nodeIdResult.ifPresent(nodeId -> {
                    try {
                        // 1. 初始化集群管理器，获取当前节点信息（角色、模式）
                        ClusterManager cm = ClusterManager.getInstance(nodeId);
                        NodeInfo selfNode = cm.getSelfNode(); // 当前节点信息
                        ClusterManager.ClusterMode mode = cm.getClusterMode(); // 集群模式（主从/分片）

                        // 2. 构造提示信息：包含节点ID、角色（主从模式下）、集群模式
                        String roleInfo = "";
                        if (mode == ClusterManager.ClusterMode.MASTER_SLAVE) {
                            roleInfo = " (角色: " + selfNode.getRole() + ")"; // 追加角色信息（MASTER/SLAVE）
                        }
                        String infoMessage = String.format("节点 '%s'%s 正在后台启动...\n模式: %s",
                                nodeId, roleInfo, mode.toString());

                        // 3. 显示集群节点启动提示
                        showInfo("集群节点启动", infoMessage);

                        // 4. 后台线程启动集群节点（避免阻塞GUI）
                        new Thread(() -> {
                            DbmsServer.main(new String[]{nodeId}); // 传入节点ID启动服务器
                        }).start();

                    } catch (Exception e) {
                        // 启动失败处理（如节点ID不存在、集群配置错误）
                        showError("启动失败", "无法启动集群节点 '" + nodeId + "':\n" + e.getMessage());
                    }
                });

                // -------------------------- 分支5：用户取消 --------------------------
            } else {
                System.out.println("Launch cancelled.");
                Platform.exit(); // 关闭JavaFX应用
            }
        }
    }

    /**
     * 辅助方法：显示信息提示弹窗（如启动成功、状态通知）
     * @param title 弹窗标题
     * @param message 弹窗内容
     */
    private void showInfo(String title, String message) {
        Alert infoAlert = new Alert(Alert.AlertType.INFORMATION);
        infoAlert.setTitle(title);
        infoAlert.setHeaderText(null); // 隐藏头部文本，简化样式
        infoAlert.setContentText(message);
        infoAlert.showAndWait(); // 阻塞等待用户关闭弹窗
    }

    /**
     * 辅助方法：显示错误提示弹窗（如格式错误、连接失败）
     * @param title 弹窗标题
     * @param message 错误内容
     */
    private void showError(String title, String message) {
        Alert errorAlert = new Alert(Alert.AlertType.ERROR);
        errorAlert.setTitle(title);
        errorAlert.setHeaderText(null); // 隐藏头部文本，简化样式
        errorAlert.setContentText(message);
        errorAlert.showAndWait(); // 阻塞等待用户关闭弹窗
    }

    /**
     * JavaFX应用程序主入口：启动Launcher
     * @param args 命令行参数（未使用）
     */
    public static void main(String[] args) {
        launch(args); // 启动JavaFX应用，触发start()方法
    }
}